-- Gemstone.lua
-- Written by jusjoken
-- used for all Gemstone and phoenix calls to SageTV

function Initialize()

	-- Global variable to ensure we get a valid connection before processing Sage information
	MyDebug = SKIN:GetVariable('LuaDebug','0')
	CheckCounter=0
	WaitForConnect = tonumber(SKIN:GetVariable('WaitForConnect'))
	CheckEvery = tonumber(SKIN:GetVariable('CheckEvery'))
	SageConnected = false
	InitComplete = false
	UpdateTime = os.time()
	
	-- Global Variables
	CWShowTitle = tonumber(SKIN:GetVariable('CWShowTitle'))
	CWShowFooter = tonumber(SKIN:GetVariable('CWShowFooter'))
	CWCondMaxChars = tonumber(SKIN:GetVariable('CWCondMaxChars'))
	-- Global variables to control if and when the weather backgrounds are changed for the Windows Wallpaper
	CWCondCode = nil
	CWSwitchWallpaper = tonumber(SKIN:GetVariable('CWSwitchWallpaper'))
	CWSwitchWallpaperDelay = tonumber(SKIN:GetVariable('CWSwitchWallpaperDelay'))
	if CWSwitchWallpaperDelay==0 then CWSwitchWallpaperDelay = -1 end
	CWSwitchWallpaperDir = SKIN:GetVariable('CWSwitchWallpaperDir','#@#Images\\Gemstone\\Weather\\Backgrounds')
	CWSwitchWallpaperTemp = SKIN:GetVariable('CWSwitchWallpaperTemp','#@#Temp\\CWSwitchWallpaperTemp.txt')
	-- By default hide some meters
	SKIN:Bang('!HideMeterGroup', 'CurrentWeather')
	SKIN:Bang('!HideMeterGroup', 'WeatherTitle')
	SKIN:Bang('!HideMeterGroup', 'WeatherFooter')

	DayStartHour = tonumber(SKIN:GetVariable('DayStartHour','7'))
	DayEndHour = tonumber(SKIN:GetVariable('DayEndHour','19'))
	UseArrowforWind = tonumber(SKIN:GetVariable('UseArrowforWind','0'))
	CurrentWeather = ''
	WLocation = ''
	WUpdated = ''
	WUnits = 'Standard'
	WTempSuffix = ' F'
	WSpeedSuffix = 'mph'
	
	-- Init anything one time here
	SKIN:Bang('!HideMeterGroup', 'CurrentWeather')
	
end

-- Weather functions
function ConnectCheck()
	CheckCounter = CheckCounter + CheckEvery
	local ThisTime = os.time()
	local ElapsedTime = ThisTime - UpdateTime
	if MyDebug=='1' then print('***Since Last Update: '..ElapsedTime..' Since Last Update: '..UpdateTime) end
	if SageConnected then
		--SKIN:Bang('!DisableMeasure', 'ConnectCheck')
		if ElapsedTime>CheckEvery+6 then
			--must not have a connection anymore
			SageConnected = false
			InitComplete = false
			CheckCounter = 0
			SKIN:Bang('!HideMeterGroup', 'CurrentWeather')
			if CWShowTitle==0 then
				SKIN:Bang('!HideMeterGroup', 'WeatherTitle')
			end
			SKIN:Bang('!HideMeterGroup', 'WeatherFooter')
			SKIN:Bang('!ShowMeter', 'pLoadingMeter')
			SKIN:Bang('!SetOption', 'pLoadingMeter', 'Text', 'Connection Lost') 
			if MyDebug=='1' then print('ConnectCheck: connection to Sage Server was LOST') end
		else
			if MyDebug=='1' then print('ConnectCheck: connected to Sage Server') end
		end
	else
		if CheckCounter>=WaitForConnect then
			--SKIN:Bang('!DisableMeasure', 'ConnectCheck')
			if MyDebug=='1' then print('ConnectCheck: check for connection expired and connection unavailable after "'..CheckCounter..'" seconds') end
			SKIN:Bang('!HideMeterGroup', 'CurrentWeather')
			if CWShowTitle==0 then
				SKIN:Bang('!HideMeterGroup', 'WeatherTitle')
			end
			SKIN:Bang('!HideMeterGroup', 'WeatherFooter')
			SKIN:Bang('!ShowMeter', 'pLoadingMeter')
			SKIN:Bang('!SetOption', 'pLoadingMeter', 'Text', 'No Connection') 
		else
			--waiting for the connection
			if MyDebug=='1' then print('ConnectCheck: still not connected after "'..CheckCounter..'" seconds') end
		end
	end
end

function WeatherInit()
	-- called only on startup 
	-- needs to enable the other measures for load and update if success
	-- if we got here then we must have received a result from Sage
	if MyDebug=='1' then print('WeatherInit: CALLED') end
	SageConnected = true
	InitComplete = true
	-- check the result to ensure we have a valid weather implementation
	local tMeasure = SKIN:GetMeasure('pWeatherInit')
	local tvalue = tMeasure:GetStringValue()
	local tresult = string.match(tvalue, 'CheckImpl":"'..'(.-)'..'",') or nil 
	if tresult=='Passed' or tresult=='Current' then 
		-- set global variables
		local value = ''
		-- set Location
		value = GetValue(tvalue,'WLocationName":"','",')
		if value~=nil then 
			WLocation = value
			value = GetValue(tvalue,'WLocation":"','"')
			if value~=nil then 
				WLocation = WLocation..' ('..value..')'
			end
			SKIN:Bang('!SetOption', 'pCWGetLocationMeter', 'Text', WLocation) 
		end
		-- set Recorded Date
		SetRecordedDate(tvalue)
		
		-- set Weather Suffix's
		value = GetValue(tvalue,'WUnits":"','",')
		if value~=nil then 
			WUnits = value
			if WUnits=='Standard' then 
				WTempSuffix = ' F'
				WSpeedSuffix = 'mph'
			else
				WTempSuffix = ' C'
				WSpeedSuffix = 'k/h'
			end
		end
		-- enable the weather measures to start updates
		if CWShowTitle==1 then
			SKIN:Bang('!ShowMeterGroup', 'WeatherTitle')
		end
		if CWShowFooter==1 then
			SKIN:Bang('!ShowMeterGroup', 'WeatherFooter')
		end
		SKIN:Bang('!ShowMeterGroup', 'CurrentWeather')
		SKIN:Bang('!HideMeter', 'pLoadingMeter')
		SKIN:Bang('!EnableMeasure', 'pCurrentWeather')
		if MyDebug=='1' then print('WeatherInit: enabled pCurrentWeather') end
	else
		SKIN:Bang('!SetOption', 'pLoadingMeter', 'Text', 'Load Failed') 
	end
	
end

function WeatherUpdate()
	if InitComplete==false then
		-- Update called but the Weather Init has not run.... so refresh this skin
		if MyDebug=='1' then print('WeatherUpdate: Refreshing to force WeatherInit to run') end
		SKIN:Bang('!Refresh')
	else
		UpdateTime = os.time()
		WeatherMeasure = SKIN:GetMeasure('pWeatherUpdate')
		WeatherUpdateValue = WeatherMeasure:GetStringValue()
		if MyDebug=='1' then print('WeatherUpdateValue: ' .. WeatherUpdateValue) end
		-- see if we have an Update available
		local tresult = string.match(WeatherUpdateValue, 'WUpdated":'..'(.-)'..'}') or nil 
		if tresult=='true' then 
			SetRecordedDate(WeatherUpdateValue)
			SKIN:Bang('!EnableMeasure', 'pCurrentWeather')
			if MyDebug=='1' then print('WeatherUpdate: completed at: ' .. UpdateTime) end
		else
			if MyDebug=='1' then print('WeatherUpdate: no update availablecompleted at: ' .. UpdateTime) end
		end
	end
end

function SetRecordedDate(SearchString)
	-- update the last updated time if valid
	local value = nil
	value = GetValue(SearchString,'WRecordedDate":"','",')
	if value~=nil then 
		SKIN:Bang('!SetOption', 'pCWGetUpdatedMeter', 'Text', value) 
		if MyDebug=='1' then print('UpdateRecorded: '..value) end
	end
end

function WeatherLoad()
	if MyDebug=='1' then print('WeatherLoad: started') end
	WeatherMeasure = SKIN:GetMeasure('pCurrentWeather')
	CurrentWeather = WeatherMeasure:GetStringValue()
	if MyDebug=='1' then print('CurrentWeather: ' .. CurrentWeather) end
	-- update each of the current weather meters
	-- as load has been called we disable the measure until an update or init is called again
	SKIN:Bang('!DisableMeasure', 'pCurrentWeather')

	local value = nil
	-- update Temp
	value = GetValue(CurrentWeather,'WFTemp": "','"')
	if value~=nil then 
		-- handle temps > 2 digits as well as 2 digit negative values by striping out the space
		if value:len()>4 then
			value = value:gsub(' ','')
		end
		SKIN:Bang('!SetOption', 'pCWGetTempMeter', 'Text', value) 
	end
	
	-- update Icon
	if IsDaytime() then
		value = GetValue(CurrentWeather,'WCodeDay": "','"')
	else
		value = GetValue(CurrentWeather,'WCodeNight": "','"')
	end
	if value~=nil then 
		SKIN:Bang('!SetOption', 'pCWGetIconMeter', 'ImageName', value..'.png')
		-- if Wallpaper switching is on and the code has changed then create a file with a list of backgrounds to use
		if value~=CWCondCode and CWSwitchWallpaper > 0 then
			CWCondCode = value
			SKIN:Bang('!SetVariable', 'CWCondCode', CWCondCode)
			
			GetFileList(CWSwitchWallpaperTemp, CWSwitchWallpaperDir..'\\'..CWCondCode)
			-- turn on the pCWSwitchWallpaper measure so the background gets changed
			SKIN:Bang('!EnableMeasure', 'pCWSwitchWallpaper')
			SKIN:Bang('!UpdateMeasure', 'pCWSwitchWallpaper')
		end
		
	end
	
	-- update Humidity
	value = GetValue(CurrentWeather,'WHumid": "','"')
	if value~=nil then 
		SKIN:Bang('!SetOption', 'pCWGetHumidMeter', 'Text', value..'%') 
	end
	
	-- update Condition
	value = GetValue(CurrentWeather,'WCondition": "','"')
	if value~=nil then 
		-- adjust the MeterStyle if the text is too long
		if value:len()>CWCondMaxChars then
			SKIN:Bang('!SetOption', 'pCWGetConditionMeter', 'MeterStyle', 'WeatherBaseStyle | WeatherItemSmallStyle') 
		else
			SKIN:Bang('!SetOption', 'pCWGetConditionMeter', 'MeterStyle', 'WeatherBaseStyle | WeatherItemStyle') 
		end
		SKIN:Bang('!SetOption', 'pCWGetConditionMeter', 'Text', value) 
	end
	
	-- update Wind
	if UseArrowforWind==0 then
		SKIN:Bang('!HideMeter', 'pCWGetWindDirMeter')
		--get the fully formatted wind string
		value = GetValue(CurrentWeather,'WWind": "','"')
		if value~=nil then 
			SKIN:Bang('!SetOption', 'pCWGetWindSpeedMeter', 'Text', value) 
		end
	else
		--use an image for the wind if there is a wind
		value = GetValue(CurrentWeather,'WWindSpeed": "','"')
		if tonumber(value)>0 then 
			value = GetValue(CurrentWeather,'WFWindSpeed": "','"')
			SKIN:Bang('!SetOption', 'pCWGetWindSpeedMeter', 'Text', value) 
			--now get the wind direction and update the arrow image
			value = GetValue(CurrentWeather,'WWindDir": "','"')
			SKIN:Bang('!SetOption', 'pCWGetWindDirMeter', 'ImageRotate', (tonumber(value)+180)) 
			SKIN:Bang('!ShowMeter', 'pCWGetWindDirMeter')
		else
			SKIN:Bang('!HideMeter', 'pCWGetWindDirMeter')
			value = GetValue(CurrentWeather,'WWind": "','"')
			if value~=nil then 
				SKIN:Bang('!SetOption', 'pCWGetWindSpeedMeter', 'Text', value) 
			end
		end
		
	end
	
	-- update the Recorded Date
	SetRecordedDate(CurrentWeather)
	
	return CurrentWeather
end

function GetValue(input,startmarker,endmarker)
	local value = string.match(input, startmarker..'(.-)'..endmarker) or nil
	if value~=nil then 
		if value~='sNotSupported' and value~='sInvalid' and value~='2147483646' and value~='2147483647' then 
			if MyDebug=='1' then print('GetValue: returning '..value) end
			return value
		else
			if MyDebug=='1' then print('GetValue: was invalid or not supported for: "'..startmarker..'" : "'..endmarker..'" from "'..input..'"') end
			return nil
		end
	else
		if MyDebug=='1' then print('GetValue: was nil for: "'..startmarker..'" : "'..endmarker..'" from "'..input..'"') end
	end
	return value
end

function IsDaytime()
	local h = tonumber(os.date("%H"))
	if h >= DayStartHour and h < DayEndHour then
		if MyDebug=='1' then print('IsDaytime: hour "' .. h..'" true - Start:'..DayStartHour..' End:'..DayEndHour) end
		return true
	else
		if MyDebug=='1' then print('IsDaytime: hour "' .. h..'" false - Start:'..DayStartHour..' End:'..DayEndHour) end
		return false
	end
end

function GetFileList(sPathTempFile, sPathToSearchIn)
	-- runs a windows script to output a directory list into the temp file specified
	--escape any path characters so the script can handle
	--sPathTempFile = sPathTempFile:gsub('\\','\\\\')
	--sPathToSearchIn = sPathToSearchIn:gsub('\\','\\\\')
	-- wscript script.js "Path to temp file" "Path to get list from" //e:jscript      
	local tScript = 'wscript #@#src\\listScript.js "'..sPathTempFile..'" "'..sPathToSearchIn..'" //e:jscript'
	if MyDebug=='1' then print('GetFileList: Script: '..tScript) end
	SKIN:Bang(tScript)
end

